<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>react</title>
    <style>
        .content {
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 10px;
        }

        .list {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            width: 120px;
            height: 120px;
            border: 1px solid #D8D8D8;
            text-align: center;
            transition: all .07s ease;
            /*text-shadow: 0 0 .5rem black;*/
        }

        .code {
            font-size: 20px;
            font-weight: bold;
            margin-bottom: 20px;
        }

        .playing {
            transform: scale(1.1);
            border-color: #ffc600;
            box-shadow: 0 0 1rem #ffc600;
        }
    </style>
</head>
<body>
<div id="root"></div>
</body>
<script src="../lib/babel.min.js"></script>
<script async src="../lib/es-module-shims.js"></script>
<script type="importmap">
        {
          "imports": {
            "react": "https://esm.sh/react?dev",
            "react-dom/client": "https://esm.sh/react-dom/client?dev"
          }
        }

</script>

<script type="text/babel" data-type="module">
    import React, {StrictMode,useState,useEffect,useRef,useCallback} from 'react';
    import {createRoot} from 'react-dom/client';

    // 自定义 Hook 优化版
    function useKeySoundController(list) {
        const audioRefs = useRef({});
        const [activeKey, setActiveKey] = useState(null);
        const timeoutIds = useRef({});

        // 稳定的音频播放方法
        const playAudio = useCallback((key) => {
            const audio = audioRefs.current[key];
            if (!audio) return;

            audio.currentTime = 0;

            // 错误处理增强
            audio.play().catch(error => {
                console.error(`播放失败 (${key}):`, error);
                setActiveKey(null); // 立即重置状态
            });
        }, []);

        // 动画状态管理
        const manageVisualState = useCallback((key) => {
            // 使用独立的定时器管理每个按键
            setActiveKey(key);
            if (timeoutIds.current[key]) {
                clearTimeout(timeoutIds.current[key]);
            }
            // 内存泄漏防护
            timeoutIds.current[key] = setTimeout(() => {
                setActiveKey(prev => (prev === key ? null : prev));
            }, 100);
        }, []);

        // 键盘事件处理
        useEffect(() => {
            const handleKeyDown = (e) => {
                const key = e.keyCode?.toString();
                if (!audioRefs.current[key]) return;

                manageVisualState(key);
                playAudio(key);
            };

            window.addEventListener('keydown', handleKeyDown);
            return () => {
                window.removeEventListener('keydown', handleKeyDown);
                // 清理所有定时器
                Object.values(timeoutIds.current).forEach(clearTimeout);
            };
        }, [manageVisualState, playAudio]);

        return { audioRefs, activeKey };
    }

    // 单个音效组件
    const SoundItem = React.memo(({ item, isActive }) => (
        // 使用 React.memo 避免不必要的重渲染
        // 独立管理每个音频元素的引用
        <div
            className={`list ${isActive ? 'playing' : ''}`}
            data-key={item.key}>
            <kbd className="code">{item.code}</kbd>
            <div>{item.sound}</div>
            <audio
                ref={ref => this.audioRef = ref}
                data-key={item.key}
                src={`sounds/${item.sound}.wav`}
            />
        </div>
    ));

    // 主组件
    function App() {
        const list = [
            { code: 'A', key: '65', sound: 'clap' },
            { code: 'S', key: '83', sound: 'hihat' },
            { code: 'D', key: '68', sound: 'kick' },
            { code: 'F', key: '70', sound: 'openhat' },
            { code: 'G', key: '71', sound: 'boom' },
            { code: 'H', key: '72', sound: 'ride' },
            { code: 'J', key: '74', sound: 'snare' },
            { code: 'K', key: '75', sound: 'tom' },
            { code: 'L', key: '76', sound: 'tink' }
        ];

        const { audioRefs, activeKey } = useKeySoundController(list);

        return (
            <div className="content">
                {list.map(item => (
                    <SoundItem
                        key={item.key}
                        item={item}
                        isActive={activeKey === item.key}
                        ref={ref => (audioRefs.current[item.key] = ref)}
                    />
                ))}
            </div>
        );
    }

    // 初始化
    const container = document.getElementById('root');
    const root = createRoot(container);

    root.render(
        <StrictMode>
            <App/>
        </StrictMode>
    );
</script>
</html>
